from PIL import Image, ImageDraw, ImageFont
import os
import sys

def get_available_fonts():
    """获取系统中可用的中文字体，优化字体查找逻辑"""
    font_candidates = []
    
    # 按系统添加可能的字体路径
    if sys.platform.startswith('win'):
        font_dirs = ['C:/Windows/Fonts', os.path.expanduser('~/.fonts')]
        font_names = ['simsun.ttc', 'simhei.ttf', 'msyh.ttc', 'msyhbd.ttc', 
                     'simkai.ttf', 'siminwei.ttf', 'microsoft yahei.ttf']
    elif sys.platform.startswith('darwin'):  # macOS
        font_dirs = ['/System/Library/Fonts', '/Library/Fonts', 
                    os.path.expanduser('~/Library/Fonts')]
        font_names = ['PingFang.ttc', 'Heiti TC', 'Songti TC', 
                     'Arial Unicode.ttf', 'Microsoft YaHei.ttf']
    else:  # Linux
        font_dirs = ['/usr/share/fonts', '/usr/local/share/fonts',
                    os.path.expanduser('~/.fonts')]
        font_names = ['simhei.ttf', 'simsun.ttc', 'wqy-zenhei.ttc',
                     'wqy-microhei.ttc', 'dejavu-sans.ttf']
    
    # 遍历所有可能的字体路径组合
    for dir_path in font_dirs:
        if os.path.exists(dir_path):
            for font_name in font_names:
                font_path = os.path.join(dir_path, font_name)
                if os.path.exists(font_path):
                    font_candidates.append(font_path)
    
    # 添加默认字体作为最后的备选
    font_candidates.append(None)
    return font_candidates

def text_to_stars(text, font_size=32, star_char='*', space_char=' '):
    """将文字转换为星号图案，采用网格采样确保整齐对齐"""
    if not text:
        print("错误：输入文字不能为空！")
        return []
    
    try:
        # 1. 网格参数设置（这是整齐的关键）
        grid_size = 2  # 网格单元大小，越小越精细，但文件越大
        margin = font_size // 4 # 边距，根据字体大小动态调整

        # 2. 计算图像尺寸，确保能容纳所有文字和边距
        # 使用一个临时字体对象来估算文字宽度
        temp_font = ImageFont.load_default()
        if get_available_fonts()[0]:
            try:
                temp_font = ImageFont.truetype(get_available_fonts()[0], font_size)
            except: pass
        
        text_bbox = temp_font.getbbox(text)
        text_width_est = text_bbox[2] - text_bbox[0]
        text_height_est = text_bbox[3] - text_bbox[1]
        
        img_width = text_width_est + margin * 2
        img_height = text_height_est + margin * 2

        # 3. 创建图像并绘制文字
        image = Image.new('L', (img_width, img_height), 255)
        draw = ImageDraw.Draw(image)
        
        # 加载字体
        available_fonts = get_available_fonts()
        font = None
        font_loaded = False
        for font_path in available_fonts:
            try:
                if font_path:
                    font = ImageFont.truetype(font_path, font_size)
                else:
                    font = ImageFont.load_default()
                font_loaded = True
                break
            except Exception as e:
                continue
        
        if not font_loaded:
            print("警告：无法加载任何字体，使用默认字体可能导致显示异常", file=sys.stderr)
            font = ImageFont.load_default()
        
        # 精确居中文字
        bbox = draw.textbbox((0, 0), text, font=font)
        text_width = bbox[2] - bbox[0]
        text_height = bbox[3] - bbox[1]
        x = (img_width - text_width) // 2
        y = (img_height - text_height) // 2
        draw.text((x, y), text, font=font, fill=0)
        
        # 4. 网格采样转换为字符图案（核心优化）
        star_pattern = []
        # 计算最终图案的总行数和总列数
        pattern_cols = img_width // grid_size
        pattern_rows = img_height // grid_size

        for y_grid in range(pattern_rows):
            line = []
            for x_grid in range(pattern_cols):
                # 计算当前网格在图像中的像素范围
                x_start = x_grid * grid_size
                y_start = y_grid * grid_size
                x_end = x_start + grid_size
                y_end = y_start + grid_size
                
                # 检查网格内是否有文字像素（值小于128）
                has_pixel = False
                for x_pixel in range(x_start, x_end):
                    for y_pixel in range(y_start, y_end):
                        if image.getpixel((x_pixel, y_pixel)) < 128:
                            has_pixel = True
                            break # 找到一个就可以退出内层循环
                    if has_pixel:
                        break # 找到一个就可以退出外层循环
                
                line.append(star_char if has_pixel else space_char)
            
            # 过滤完全空白的行，避免上下出现多余的空行
            line_str = ''.join(line).rstrip(space_char)
            if line_str:
                star_pattern.append(line_str)
        
        return star_pattern
    
    except Exception as e:
        print(f"转换过程出错: {str(e)}", file=sys.stderr)
        return []

def print_star_pattern(pattern):
    """打印星号图案，确保整体对齐整齐"""
    if not pattern:
        print("没有可显示的图案")
        return
    
    # 确保所有行长度完全一致
    max_len = max(len(line) for line in pattern) if pattern else 0
    standardized_pattern = [line.ljust(max_len, ' ') for line in pattern]
    
    # 打印带边框的整齐图案
    print("\n" + "=" * (max_len + 4))
    for line in standardized_pattern:
        print(f"  {line}  ")
    print("=" * (max_len + 4) + "\n")

if __name__ == "__main__":
    print("===== 文字转星号图案程序（网格对齐版） =====")
    print("提示：输入完成后按回车确认，直接回车使用默认值\n")
    
    try:
        input_text = input("请输入要转换的文字: ").strip()
        while not input_text:
            input_text = input("文字不能为空，请重新输入: ").strip()
        
        while True:
            font_input = input("请输入字体大小(默认32，建议24-48): ").strip()
            if not font_input:
                font_size = 32
                break
            try:
                font_size = int(font_input)
                if 16 <= font_size <= 64:
                    break
                else:
                    print("请输入16-64之间的数字")
            except ValueError:
                print("请输入有效的数字")
        
        star_char = input("请输入填充字符(默认*，建议单个字符): ").strip() or '*'
        star_char = star_char[0] if star_char else '*'
        
        space_char = input("请输入空白字符(默认空格): ").strip() or ' '
        space_char = space_char[0] if space_char else ' '
        
        print("\n正在生成图案...")
        star_pattern = text_to_stars(input_text, font_size, star_char, space_char)
        print_star_pattern(star_pattern)
        
    except KeyboardInterrupt:
        print("\n程序已取消")
    except Exception as e:
        print(f"程序出错: {str(e)}")